Reverse switches on the stored condition instead of a control-flow tape - #1918
Merged
Conversation
vgvassilev
force-pushed
the
switch-cond-reverse
branch
from
July 21, 2026 19:14
897a4d6 to
e8e9dfe
Compare
| Sema::ConditionResult revCondRes = | ||
| m_Sema.ActOnCondition(getCurrentScope(), noLoc, CloneNode(condExpr), | ||
| Sema::ConditionKind::Switch); | ||
| SwitchStmt* reverseSS = |
Contributor
There was a problem hiding this comment.
warning: use auto when initializing with a template cast to avoid duplicating the type name [modernize-use-auto]
Suggested change
| SwitchStmt* reverseSS = | |
| auto* reverseSS = |
| ++i) { | ||
| SwitchCase* rev = nullptr; | ||
| if (isa<DefaultStmt>(SSData.cases[i])) { | ||
| rev = new (m_Context) DefaultStmt(noLoc, noLoc, inner); |
Contributor
There was a problem hiding this comment.
warning: assigning newly created 'gsl::owner<>' to non-owner 'SwitchCase *' [cppcoreguidelines-owning-memory]
rev = new (m_Context) DefaultStmt(noLoc, noLoc, inner);
^
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
Reverse-mode differentiation of a switch statement recorded, in a second control-flow tape, which case a `break` exited from, then re-dispatched the reverse sweep by popping that tape. The information is redundant: the switch condition is already stored (`_cond`), and every case guard already compares against it (`if (v == _cond) break`). The extra tape -- and the BreakContStmtHandler state backing it -- only duplicated what the condition carries. Drop the control-flow tape for switches and re-switch on the stored condition directly. Each fall-through group's reverse entry is now labelled with its original case values rather than a synthesized counter, and the trailing group (closed by the switch end rather than a break) is labelled in VisitSwitchStmt. The per-case guards are unchanged. Loops keep their control-flow tape, where a break's iteration genuinely cannot be recovered from a condition. This is behaviour-preserving: all Switch.C/SwitchInit.C execution results are unchanged; only the generated code -- forward (the counter pushes are gone) and reverse -- and its FileCheck baselines change, with one fewer tape. A switch whose cases return rather than break is added to Switch.C to cover the returning-case shape. SwitchInit.C no longer needs its Valgrind XFAIL: the control-flow tape it tripped on under memcheck is gone.
vgvassilev
force-pushed
the
switch-cond-reverse
branch
from
July 21, 2026 21:16
e8e9dfe to
b6d553b
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Reverse-mode differentiation of a switch statement recorded, in a second control-flow tape, which case a
breakexited from, then re-dispatched the reverse sweep by popping that tape. The information is redundant: the switch condition is already stored (_cond), and every case guard already compares against it (if (v == _cond) break). The extra tape -- and the BreakContStmtHandler state backing it -- only duplicated what the condition carries.Drop the control-flow tape for switches and re-switch on the stored condition directly. Each fall-through group's reverse entry is now labelled with its original case values rather than a synthesized counter, and the trailing group (closed by the switch end rather than a break) is labelled in VisitSwitchStmt. The per-case guards are unchanged. Loops keep their control-flow tape, where a break's iteration genuinely cannot be recovered from a condition.
This is behaviour-preserving: all Switch.C/SwitchInit.C execution results are unchanged; only the generated code -- forward (the counter pushes are gone) and reverse -- and its FileCheck baselines change, with one fewer tape. A switch whose cases return rather than break is added to Switch.C to cover the returning-case shape.